/*
 * TestPersistor.cpp
 *
 */

#include "TestPersistor.h"

#include <list>
#include "../../src/logical_layer/bplustree/PersistorPool.h"
#include "../../src/physical_layer/Block.h"
#include "../../src/logical_layer/bplustree/Element.h"
#include "../../src/logical_layer/bplustree/LeafNode.h"
#include "../../src/logical_layer/bplustree/Node.h"
#include "../../src/utils/StringUtils.h"
#include "../../src/logical_layer/bplustree/ElementFactory.h"
#include <assert.h>
TestPersistor::TestPersistor() {
	fileName = "testPersistor";
	blockSize = 1024;
}

TestPersistor::~TestPersistor() {
}

void TestPersistor::runTests() {

		testInit();
		testAddLeafNode();
		testLoadLeafNode();
		testModifyLeafNode();
		testLoadLeafNode();
		testRemoveLeafNode();
		testRootNode();
		std::cout << "Test Persistor OK" << std::endl;
		PersistorPool::dropInstance(ELEMENT);
}

void TestPersistor::testInit() {
	std::cout << "********Test Persistor Initialization********" << std::endl;
	try {
		//Persistor::init("test.txt",1024);
		//PersistorBTree *persistor = Persistor::getInstance();
		string filename = "test_init";
		int block_size = 64;
		PersistorPool::init(filename, block_size, ELEMENT);
		PersistorBTree *persistor = PersistorPool::getInstance(ELEMENT);
		PersistorPool::dropInstance(ELEMENT);
		//persistor->deleteFile();
		//delete persistor;
	}
	/*catch(PersistorNotInitializedException e) {
	 std::cout << "Paso Test!" << std::endl;
	 }*/
	catch (...) {
		std::cout << "Error en test!" << std::endl;
	}

	//std::cout << "Error en test!" << std::endl;


	std::cout << std::endl;
	std::cout << "********Test Persistor Initialization OK********" << std::endl;

}

void TestPersistor::testAddLeafNode() {
	std::cout << "********Test Persistor Add LeafNode********" << std::endl;
	LeafNode *leafNodo = new LeafNode();

	std::string data1 = "Me guarde 1";
	std::string data2 = "Me guarde 2";
	std::string data3 = "Me guarde 3";

	leafNodo->setLevel(0);
	leafNodo->setOffset(0);
	leafNodo->insertarTest(ElementFactory::createElement(ELEMENT,100, (Data) data1.c_str(),
			data1.length()));
	leafNodo->insertarTest(ElementFactory::createElement(ELEMENT,200, (Data) data2.c_str(),
			data2.length()));
	leafNodo->insertarTest(ElementFactory::createElement(ELEMENT,300, (Data) data3.c_str(),
			data3.length()));
	//PersistorBTree *persistor = Persistor::getInstance(); //REFACTOR
	string filename = "test_addLeafNode";
	int block_size = 128;
	PersistorPool::init(filename, block_size, ELEMENT);
	PersistorBTree *persistor = PersistorPool::getInstance(ELEMENT);
	persistor->add(leafNodo);
	//PersistorPool::dropInstance(ELEMENT);

//	delete persistor;
	delete leafNodo;
	std::cout << "********Test Persistor Add LeafNode  OK********" << std::endl;
}

void TestPersistor::testLoadLeafNode() {
	std::cout << "********Test Persistor LoadLeafNode********" << std::endl;

	LeafNode *leafNodo = new LeafNode();

	//PersistorBTree *persistor = Persistor::getInstance(); //REFACTOR
	string filename = "load_leaf_node";
	int block_size = 128;
	//PersistorPool::init(filename, block_size, ELEMENT);
	PersistorBTree *persistor = PersistorPool::getInstance(ELEMENT);
	persistor->load(1, leafNodo);

	std::cout << "Prev Node: " << leafNodo->getPrevNode() << std::endl;
	std::cout << "Next Node: " << leafNodo->getNextNode() << std::endl;
	std::cout << "FreeSpace: " << leafNodo->getFreeSpace() << std::endl;
	std::cout << std::endl;

	std::vector<IElement*>::iterator it;

	for (it = leafNodo->getElementsBegin(); it != leafNodo->getElementsEnds(); it++) {
		std::cout << "Key: " << (*it)->getKey() << std::endl;
		std::cout << "Tamanno del elemento: "
				<< ((Element*) (*it))->getElementSize() << std::endl;
		std::cout << "Elemento : " << ((Element*) (*it))->getData()
				<< std::endl << std::endl;
	}

	std::cout << std::endl;
//	PersistorPool::dropInstance(ELEMENT);

//	delete persistor;
	delete leafNodo;
	std::cout << "Test Persistor LoadLeafNode OK" << std::endl;
}

void TestPersistor::testModifyLeafNode() {
	std::cout << "Test Persistor ModifyLeafNode" << std::endl;
	LeafNode *leafNodo = new LeafNode();

	//PersistorBTree *persistor = Persistor::getInstance(); REFACTOR
//	string filename = "load_leaf_node";
//	PersistorPool::init(filename, blockSize, ELEMENT);
	PersistorBTree *persistor = PersistorPool::getInstance(ELEMENT);
	persistor->load(1, leafNodo);

	IElement* el = leafNodo->getElement(GenericKey((ID)200));

	std::string data = "Me modifique!!";

	((Element*) el)->setData((Data) data.c_str(), data.length());

	persistor->modify(leafNodo);

	delete leafNodo;
	std::cout << "Test Persistor ModifyLeafNode    OK" << std::endl;
}

void TestPersistor::testAddNode() {
}

void TestPersistor::testLoadNode() {
}

void TestPersistor::testRemoveLeafNode() {
	std::cout << "Test Persistor RemoveLeafNode" << std::endl;

	//PersistorBTree *persistor = Persistor::getInstance(); REFACTOR
//	string filename = "test_removeLeafNode";
//	PersistorPool::init(filename, blockSize, ELEMENT);
	PersistorBTree *persistor = PersistorPool::getInstance(ELEMENT);
	persistor->removeBlock(0);
	//PersistorPool::dropInstance(ELEMENT);

	//delete persistor;
	std::cout << "Test Persistor RemoveLeafNode    OK" << std::endl;
}

void TestPersistor::testRootNode() {
	std::cout << "Test Persistor RootNode" << std::endl;
	PersistorBTree *bPersistor = new PersistorBTree("testNode.txt", 512,ELEMENT);

	BNode *root = bPersistor->getRoot();

	std::cout << "Level: " << root->getLevel() << std::endl;
	assert(0==root->getLevel());
	assert(ELEMENT==root->getEstructura());

	delete bPersistor;
	delete root;
	std::cout << "Test Persistor RootNode    OK" << std::endl;
}
